﻿/*

   -----------------------
   UDP-Receive (send to)
   -----------------------
   // http://msdn.microsoft.com/de-de/library/bb979228.aspx#ID0E3BAC
   This class receives the facedata from FaceStreamer on UDP 127.0.0.1:29129
 

*/
using System.Collections;

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace Handsfree
{
    public class UDPReceive
    {
        #region Member Variables
        // receiving Thread
        Thread receiveThread;

        UdpClient client;
        // public string IP = "127.0.0.1"; default local
        public int port; // define > init

        //for Mouse Operations
        MouseOperations m = new MouseOperations();

        // infos
        public string lastReceivedUDPPacket = "";
        // FaceAPI data
        public static float xPos, yPos, zPos;
        public static float pitch, yaw, roll;

        #region Cursor Control Variables
        public static bool isEnabled, recalibrate;
        public static float defaultPitch, defaultYaw;
        public static int delX, delY;
        public static float Xmean, Ymean;
        long fps;
        #endregion Cursor Control Variables

        #endregion

        #region Constructor
        /* Constructor
         *      Sets the value for port
         *      Begins the receiving thread
         */
        public UDPReceive()
        {
            xPos = 0;
            yPos = 0;
            zPos = 0;
            pitch = 0;
            yaw = 0;
            roll = 0;
            ///define Port
            port = 29129;

            
            InitializeCursorControlVariables();
            /* Receive Thread
             * -------------------
             * method ReceviveData() begins in a new Thread receiveThread while
             * function parseString() parses the last read string and breaks it
             * into different variables
             */
            receiveThread = new Thread(new ThreadStart(ReceiveData));
            receiveThread.IsBackground = true;
            receiveThread.Start();
        }
        public UDPReceive(bool a)
        {
            /*
             * Overload Constructor
             * Allows calling methods from objects but does not
             * start the Receive and MouseControl Threads
             */

        }
        public void InitializeCursorControlVariables()
        {
            Xmean = 10.0f;
            Ymean = 10.0f;
            defaultYaw = 0;
            defaultPitch = 0;
            fps = 0;
            recalibrate = true;
        }
        public void StartEngine()
        {
            isEnabled = true;
        }
        public void StopEngine()
        {
            isEnabled = false;
        }
        #endregion

        #region Methods
        public string getLastPacket()
        {
            return lastReceivedUDPPacket;
        }

        
        // receive thread
        public void ReceiveData()
        {
            client = new UdpClient(port);
            while (true)
            {

                try
                {
                    // Receive Bytes.
                    IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
                    byte[] data = client.Receive(ref anyIP);

                    // Convert Bytes to UTF8-Kodierung i.e. Textformat
                    string text = Encoding.UTF8.GetString(data);

                    parseString(text);
                    // latest UDPpacket
                    lastReceivedUDPPacket = text;

                    //Move Mouse if isEnabled is true
                    long mod = 1L;// pref.getSpeedValue() * 10000000L;
                    fps = fps++ % mod;
                    if(isEnabled==true)
                        UpdateCursor();
                }
                catch (Exception err)
                {
                    //MessageBox.Show(err.ToString());
                }
            }
        }

        public void parseString(String text)
        {

            String[] str = text.Split(' ');
            int index = 0;
            xPos = float.Parse(str[index++]);
            yPos = float.Parse(str[index++]);
            zPos = float.Parse(str[index++]);
            pitch = -1*float.Parse(str[index++]);
            yaw = -1*float.Parse(str[index++]);
            roll = float.Parse(str[index++]);
         }
        
        // getLatestUDPPacket
        // cleans up the rest
        public string getLatestUDPPacket()
        {
            return lastReceivedUDPPacket;
        }

        public void init()
        {
            defaultPitch = pitch;
            defaultYaw = yaw;
        }

        public void UpdateCursor()
        {
            calibrate();
            Preferences pref = new Preferences();
            int speed=pref.getSpeedValue();
            int dX = (int)delX*speed;
            int dY = (int)delY*speed;
            m.MoveMouse(dX,dY);

        }
        public void calibrate()
        {
            delX = 0;
            delY = 0;

            if (!(roll == 0 && pitch == 0 && yaw == 0))
            {
                if (recalibrate)
                {
                    init();
                    recalibrate = false;
                }
            }
            else
            {
                recalibrate = true;
                return;
            }
            if (pitch - defaultPitch > Ymean)
                delY = 1;//(int)(pitch-defaultPitch)/5;
            else if (pitch - defaultPitch < (-1 * Ymean))
                delY = -1;// -((int)(-pitch - defaultPitch) / 5);
            if (yaw - defaultYaw > Xmean)
                delX = 1;//(int)(yaw - defaultYaw)/5;
            else if (yaw - defaultYaw < (-1 * Xmean))
                delX = -1;//-((int)(-yaw-defaultYaw)/5);
             
        }
        #endregion

        void stopClient()
        {
            if (receiveThread != null)
                receiveThread.Abort();
            client.Close();
        }
        
    }
}